﻿using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Security;
using System.Security.Cryptography;
using System.Security.Cryptography.X509Certificates;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading;
using System.Web;

namespace OF.Utility
{
    /// <summary>
    /// 人工智能接口调用帮助类
    /// </summary>
    public class AIHelper
    {
        //阿里云
        private const string host = "https://dm-53.data.aliyun.com";
        private const string path = "/rest/160601/ocr/ocr_vehicle.json";
        private const string method = "POST";
        private const string appcode = "e28c9eb1c9f04378b8a866f26b43bc2d";

        //腾讯云
        private const string txAppid = "1255811496";
        private const string txBucket = "tencentyun";
        private const string txSecretId = "AKIDpTrzzjHZeU6TbVauKVTChx4btwjGubO6";
        private const string txSecretKey = "g7IDtVwFn9F4h4C8oDMFsGNEpFRO7csu";
        private const string txHost = "service.image.myqcloud.com";

        //face++
        private const string fcepiKey = "jC53uijhHCjq_F7672BZYeFLTbKbjN_t";
        private const string fceApiSecret = "kawvg4vpz_Xw7TZJOQT_ahHV9WDsek8U";

        #region 阿里云

        /// <summary>
        /// 图片物理路径
        /// </summary>
        /// <param name="filePath"></param>
        /// <param name="appcode"></param>
        public static string GetDriverLicenseInfo(string filePath, string appcode = "e28c9eb1c9f04378b8a866f26b43bc2d")
        {
            string szReturn = string.Empty;
            String querys = "";
            String bodys = "{\"inputs\":[{\"image\":{\"dataType\":50,\"dataValue\":\"BASE64\"}}]}";
            String url = host + path;
            HttpWebRequest httpRequest = null;
            HttpWebResponse httpResponse = null;
            var szBase64 = ImageHelper.ImageToBase64Str(filePath);
            bodys = bodys.Replace("BASE64", szBase64);
            if (0 < querys.Length)
            {
                url = url + "?" + querys;
            }

            if (host.Contains("https://"))
            {
                ServicePointManager.ServerCertificateValidationCallback = new RemoteCertificateValidationCallback(CheckValidationResult);
                httpRequest = (HttpWebRequest)WebRequest.CreateDefault(new Uri(url));
            }
            else
            {
                httpRequest = (HttpWebRequest)WebRequest.Create(url);
            }
            httpRequest.Method = method;
            httpRequest.Headers.Add("Authorization", "APPCODE " + appcode);
            //根据API的要求，定义相对应的Content-Type
            httpRequest.ContentType = "application/json; charset=UTF-8";
            if (0 < bodys.Length)
            {
                byte[] data = Encoding.UTF8.GetBytes(bodys);
                using (Stream stream = httpRequest.GetRequestStream())
                {
                    stream.Write(data, 0, data.Length);
                }
            }
            try
            {
                httpResponse = (HttpWebResponse)httpRequest.GetResponse();
                Stream st = httpResponse.GetResponseStream();
                StreamReader reader = new StreamReader(st, Encoding.GetEncoding("utf-8"));
                szReturn = reader.ReadToEnd();
            }
            catch (WebException ex)
            {
                httpResponse = (HttpWebResponse)ex.Response;
            }
            catch (Exception ex)
            {

            }
            return szReturn;
        }
        public static bool CheckValidationResult(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors errors)
        {
            return true;
        }

        #endregion

        #region 腾讯云

        /// <summary>
        /// 调用腾讯云服务获取行驶证/驾驶证信息
        /// </summary>
        /// <param name="filefullPath"></param>
        /// <returns></returns>
        public static string GetTencentDrivinglicence(string filefullPath)
        {
            //官方API请求格式
            //POST / ocr / drivinglicence HTTP / 1.1
            //Authorization: FCHXdPTEwMDAwMzc5Jms9QUtJRGVRZDBrRU1yM2J4ZjhRckJi ==
            //Host: recognition.image.myqcloud.com
            //Content - Length: 735
            //Content - Type: multipart / form - data; boundary = --------------acebdf13572468

            //       ----------------acebdf13572468
            //Content - Disposition: form - data; name = "appid";

            //            123456
            //            ----------------acebdf13572468
            //Content - Disposition: form - data; name = "bucket";

            //            test
            //            ----------------acebdf13572468
            //Content - Disposition: form - data; name = "type";

            //            1
            //            ----------------acebdf13572468
            //Content - Disposition: form - data; name = "image"; filename = "test.jpg"
            //Content - Type: image / jpeg

            //xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
            //----------------acebdf13572468--

            string postUrl = "http://recognition.image.myqcloud.com/ocr/general";
            string htmlContent = "";
            HttpWebRequest request;

            try
            {
                request = (HttpWebRequest)WebRequest.Create(new Uri(postUrl));
                Stream memStream = new MemoryStream();
                request.Method = "POST";
                string boundary = "--------------" + DateTime.Now.Ticks.ToString("x");// 边界符  
                request.ContentType = "multipart/form-data; boundary=" + boundary;
                byte[] enter = Encoding.ASCII.GetBytes("\r\n");  //换行
                memStream.Write(enter, 0, enter.Length);
                Dictionary<string, object> dic = new Dictionary<string, object>()
                {
                    {"appid",txAppid} ,
                    {"bucket",txBucket},
                    {"type",0 }
                };

                //写入文本字段
                string inputPartHeaderFormat = "--" + boundary + "\r\n" + "Content-Disposition:form-data;name=\"{0}\";" + "\r\n\r\n{1}\r\n";
                foreach (var kv in dic)
                {
                    string inputPartHeader = string.Format(inputPartHeaderFormat, kv.Key, kv.Value);
                    var inputPartHeaderBytes = Encoding.ASCII.GetBytes(inputPartHeader);
                    memStream.Write(inputPartHeaderBytes, 0, inputPartHeaderBytes.Length);
                }
                var fileStream = new FileStream(filefullPath, FileMode.Open, FileAccess.Read);
                // 写入文件  
                string imagePartHeader = "--" + boundary + "\r\n" +
                                         "Content-Disposition: form-data; name=\"{0}\"; filename=\"{1}\"\r\n" +
                                         "Content-Type: image/jpeg\r\n\r\n";
                var header = string.Format(imagePartHeader, "image", "bmcw.jpg");
                var headerbytes = Encoding.UTF8.GetBytes(header);
                memStream.Write(headerbytes, 0, headerbytes.Length);
                var buffer = new byte[1024];
                int bytesRead;
                while ((bytesRead = fileStream.Read(buffer, 0, buffer.Length)) != 0)
                {
                    memStream.Write(buffer, 0, bytesRead);
                }
                // 最后的结束符  
                byte[] endBoundary = Encoding.ASCII.GetBytes("xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + "\r\n" + boundary + "--\r\n");
                memStream.Write(endBoundary, 0, endBoundary.Length);

                request.ContentLength = memStream.Length;
                request.Headers.Add(HttpRequestHeader.Authorization, HmacSha1Sign());
                request.Host = txHost;

                var requestStream = request.GetRequestStream();
                memStream.Position = 0;
                memStream.CopyTo(requestStream);
                HttpWebResponse response = (HttpWebResponse)request.GetResponse();
                StreamReader sr = new StreamReader(response.GetResponseStream(), Encoding.UTF8);
                htmlContent = sr.ReadToEnd();
                sr.Close();
                response.Close();
                requestStream.Close();
                memStream.Close();
            }
            catch (WebException wex)
            {
                StringBuilder sb = new StringBuilder();
                sb.AppendLine(wex.Message);
                sb.AppendLine(wex.StackTrace);
                sb.AppendLine(wex.Source);
                // Log4netLog.Fatal(sb.ToString());
            }
            catch (InvalidOperationException ioex)
            {
                StringBuilder sb = new StringBuilder();
                sb.AppendLine(ioex.Message);
                sb.AppendLine(ioex.StackTrace);
                sb.AppendLine(ioex.Source);
                //Log4netLog.Fatal(sb.ToString());
            }
            finally
            {
                request = null;
            }
            return htmlContent;
        }

        /// <summary>
        /// 获取要加密的字符串
        /// </summary>
        /// <returns></returns>
        private static string GetOrignal()
        {
            var current = GenerateCurrentTimeStamp();
            var expired = GenerateCurrentTimeStamp() + 2592000;
            return $"a={txAppid}&b={txBucket}&k={txSecretId}&e={expired}&t={current}&r={GenerateNonceStr()}&u=0&f=";
        }

        /// <summary>
        /// HMAC-SHA1加密算法
        /// </summary>
        /// <param name="secret">密钥</param>
        /// <returns></returns>
        public static string HmacSha1Sign()
        {
            var hmacsha1 = new HMACSHA1(Encoding.UTF8.GetBytes(txSecretKey));
            var dataBuffer = Encoding.UTF8.GetBytes(GetOrignal());
            var hashBytes = hmacsha1.ComputeHash(dataBuffer);
            List<byte> bytes = new List<byte>();
            bytes.AddRange(hashBytes);
            bytes.AddRange(dataBuffer);
            return Convert.ToBase64String(bytes.ToArray());
        }

        /// <summary>
        /// 生成当前时间戳
        /// 标准北京时间，时区为东八区，自1970年1月1日 0点0分0秒以来的秒数
        /// </summary>
        /// <returns>@return 时间戳</returns>
        public static long GenerateCurrentTimeStamp()
        {
            TimeSpan ts = DateTime.UtcNow - new DateTime(1970, 1, 1, 0, 0, 0, 0);
            return Convert.ToInt64(ts.TotalSeconds);
        }

        /// <summary>
        /// 生成随机串，随机串包含字母或数字
        /// </summary>
        /// <returns> @return 随机串</returns>
        public static string GenerateNonceStr()
        {
            return DateTime.Now.ToString("yyMMddHHmm");
        }

        #endregion

        #region face++

        public class FileParameter
        {
            public byte[] File
            {
                get;
                set;
            }

            public string FileName
            {
                get;
                set;
            }

            public string ContentType
            {
                get;
                set;
            }

            public FileParameter(byte[] file) : this(file, null)
            {
            }

            public FileParameter(byte[] file, string filename) : this(file, filename, null)
            {
            }

            public FileParameter(byte[] file, string filename, string contenttype)
            {
                this.File = file;
                this.FileName = filename;
                this.ContentType = contenttype;
            }
        }

        private static readonly Encoding encoding = Encoding.UTF8;
        /// <summary>
        /// MultipartForm请求
        /// </summary>
        /// <param name="filefullPath">文件地址</param>
        /// <returns></returns>
        public static string GetFaceDrivinglicence(string filefullPath)
        {
            string text = string.Format("----------{0:N}", Guid.NewGuid());
            string contentType = "multipart/form-data; boundary=" + text;//multipart类型
            Dictionary<string, object> verifyPostParameters = new Dictionary<string, object>();
            verifyPostParameters.Add("api_key", fcepiKey);
            verifyPostParameters.Add("api_secret", fceApiSecret);
            Bitmap bmp = new Bitmap(filefullPath); // 图片地址
            byte[] fileImage;
            using (Stream stream1 = new MemoryStream())
            {
                bmp.Save(stream1, ImageFormat.Jpeg);
                byte[] arr = new byte[stream1.Length];
                stream1.Position = 0;
                stream1.Read(arr, 0, (int)stream1.Length);
                stream1.Dispose();
                fileImage = arr;
            }
            bmp.Dispose();
            //添加图片参数
            verifyPostParameters.Add("image_file", new FileParameter(fileImage, "bmcw.jpg", "application/octet-stream"));
            byte[] multipartFormData = GetMultipartFormData(verifyPostParameters, text);
            HttpWebResponse httpResponse = PostForm("https://api-cn.faceplusplus.com/cardpp/v1/ocrvehiclelicense", "", contentType, multipartFormData);
            using (Stream st = httpResponse.GetResponseStream())
            {
                StreamReader reader = new StreamReader(st, Encoding.GetEncoding("utf-8"));
                string result = reader.ReadToEnd();
                return new Regex(@"\\u([0-9A-F]{4})", RegexOptions.IgnoreCase | RegexOptions.Compiled).Replace(
     result, x => string.Empty + Convert.ToChar(Convert.ToUInt16(x.Result("$1"), 16)));

            }
        }

        private static HttpWebResponse PostForm(string postUrl, string userAgent, string contentType, byte[] formData)
        {
            HttpWebRequest httpWebRequest = WebRequest.Create(postUrl) as HttpWebRequest;
            if (httpWebRequest == null)
            {
                throw new NullReferenceException("request is not a http request");
            }

            httpWebRequest.Method = "POST";//post方式
            httpWebRequest.SendChunked = false;
            httpWebRequest.KeepAlive = true;
            httpWebRequest.Proxy = null;
            httpWebRequest.Timeout = Timeout.Infinite;
            httpWebRequest.ReadWriteTimeout = Timeout.Infinite;
            httpWebRequest.AllowWriteStreamBuffering = false;
            httpWebRequest.ProtocolVersion = HttpVersion.Version11;
            httpWebRequest.ContentType = contentType;
            httpWebRequest.CookieContainer = new CookieContainer();
            httpWebRequest.ContentLength = formData.Length;

            try
            {
                using (Stream requestStream = httpWebRequest.GetRequestStream())
                {
                    int bufferSize = 4096;
                    int position = 0;
                    while (position < formData.Length)
                    {
                        bufferSize = Math.Min(bufferSize, formData.Length - position);
                        byte[] data = new byte[bufferSize];
                        Array.Copy(formData, position, data, 0, bufferSize);
                        requestStream.Write(data, 0, data.Length);
                        position += data.Length;
                    }
                    requestStream.Close();
                }
            }
            catch (Exception ex)
            {
                return null;
            }

            HttpWebResponse result;
            try
            {
                result = (httpWebRequest.GetResponse() as HttpWebResponse);
            }
            catch (WebException arg_9C_0)
            {
                result = (arg_9C_0.Response as HttpWebResponse);
            }
            return result;
        }

        //public static bool CheckValidationResult(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors errors)
        //{
        //    return true;
        //}

        /// <summary>
        /// 从表单中获取数据
        /// </summary>
        /// <param name="postParameters"></param>
        /// <param name="boundary"></param>
        /// <returns></returns>
        private static byte[] GetMultipartFormData(Dictionary<string, object> postParameters, string boundary)
        {
            Stream stream = new MemoryStream();
            bool flag = false;
            foreach (KeyValuePair<string, object> current in postParameters)
            {
                if (flag)
                {
                    stream.Write(encoding.GetBytes("\r\n"), 0, encoding.GetByteCount("\r\n"));
                }
                flag = true;
                if (current.Value is FileParameter)
                {
                    FileParameter fileParameter = (FileParameter)current.Value;
                    string s = string.Format("--{0}\r\nContent-Disposition: form-data; name=\"{1}\"; filename=\"{2}\"\r\nContent-Type: {3}\r\n\r\n", new object[]
                    {
                        boundary,
                        current.Key,
                        fileParameter.FileName ?? current.Key,
                        fileParameter.ContentType ?? "application/octet-stream"
                    });
                    stream.Write(encoding.GetBytes(s), 0, encoding.GetByteCount(s));
                    stream.Write(fileParameter.File, 0, fileParameter.File.Length);
                }
                else
                {
                    string s2 = string.Format("--{0}\r\nContent-Disposition: form-data; name=\"{1}\"\r\n\r\n{2}", boundary, current.Key, current.Value);
                    stream.Write(encoding.GetBytes(s2), 0, encoding.GetByteCount(s2));
                }
            }
            string s3 = "\r\n--" + boundary + "--\r\n";
            stream.Write(encoding.GetBytes(s3), 0, encoding.GetByteCount(s3));
            stream.Position = 0L;
            byte[] array = new byte[stream.Length];
            stream.Read(array, 0, array.Length);
            stream.Close();
            return array;
        }
        #endregion
    }
}
